package com.tongtech.system.service.impl;

import com.tongtech.common.core.utils.CryptoUtil;
import com.tongtech.common.datascope.annotation.DataScope;
import com.tongtech.common.mail.service.MailService;
import com.tongtech.common.security.utils.SecurityUtils;
import com.tongtech.system.api.domain.SysUser;
import com.tongtech.system.domain.*;
import com.tongtech.system.enums.InformationPublishStatus;
import com.tongtech.system.enums.InformationRePublish;
import com.tongtech.system.enums.InformationToAllUser;
import com.tongtech.system.mapper.InformationMapper;
import com.tongtech.system.service.*;
import org.apache.commons.lang3.StringUtils;
import org.markdown4j.Markdown4jProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.mail.MessagingException;
import javax.sound.sampled.Line;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * 资讯管理 服务实现
 *
 * @author xingyc
 */
@Service
public class InformationServiceImpl implements IInformationService {

    private static final Logger log = LoggerFactory.getLogger(InformationServiceImpl.class);

    @Value("${spring.mail.username}")
    private String fromMail;

    @Value("${website.host}")
    private String websiteHost;

    @Autowired
    private InformationMapper informationMapper;

    @Autowired
    private IInformationCategoryService informationCategoryService;

    @Autowired
    private IInformationCategorySubscribeService informationCategorySubscribeService;

    @Autowired
    private MailService mailService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private ICustomerService customerService;

    @Autowired
    private IInformationPushLogService pushLogService;

    /**
     * 查询资讯管理数据
     *
     * @param information 资讯信息
     * @return 资讯信息集合
     */
    @Override
    @DataScope(deptAlias = "information")
    public List<Information> selectInformationList(Information information) {
        setCategoryAncestors(information);
        return informationMapper.selectInformationList(information);
    }

    /**
     * 查询资讯管理数据
     *
     * @param information 资讯信息
     * @return 资讯信息集合
     */
    @Override
    @DataScope(deptAlias = "information")
    public List<Information> selectInformationListClient(Information information) {
        setCategoryAncestors(information);
        List<Information> informationList = informationMapper.selectInformationListClient(information);
        if(!CollectionUtils.isEmpty(informationList)){
            //对资讯id进行加密
            informationList.forEach(item -> {
                Long informationId = item.getInformationId();
                String encrypt = CryptoUtil.encrypt(informationId.toString());
                item.setInformationId(null);
                item.setInformationIdStr(encrypt);
            });
        }
        return informationList;
    }

    private void setCategoryAncestors(Information information){
        Long informationCategoryId = information.getInformationCategoryId();
        if(Objects.nonNull(informationCategoryId)){
            InformationCategory informationCategory = informationCategoryService.selectInformationCategoryById(informationCategoryId);
            if(Objects.nonNull(informationCategory)){
                String ancestors = informationCategory.getAncestors();
                ancestors = ancestors + "," + informationCategoryId;
                information.setInformationCategoryAncestors(ancestors);
            }
        }
    }

    /**
     * 根据资讯ID查询信息
     *
     * @param information 资讯ID
     * @return 资讯信息
     */
    @Override
    public Information selectInformationById(Long information) {
        Information dbInformation = informationMapper.selectInformationById(information);
        //判断是否订阅该资讯，若资讯的上级资讯分类被订阅，则证明订阅了该类型的资讯。
        if (Objects.nonNull(information)) {
            Long informationCategoryId = dbInformation.getInformationCategoryId();
            if(Objects.nonNull(informationCategoryId)){
                InformationCategory informationCategory = informationCategoryService.selectInformationCategoryById(informationCategoryId);
                if(Objects.nonNull(informationCategory)){
                    String categoryName = informationCategory.getCategoryName();
                    dbInformation.setInformationCategoryName(categoryName);
                }
                Long userId = SecurityUtils.getUserId();
                InformationCategorySubscribe informationCategorySubscribe = informationCategorySubscribeService.selectInformationCategorySubscribeByUserIdCategoryId(userId, informationCategoryId);
                if (Objects.nonNull(informationCategorySubscribe)) {
                    dbInformation.setSubscribed(true);
                }
            }

        }
        return dbInformation;
    }

    private void setInformationAncestors(Information information){
        Long informationCategoryId = information.getInformationCategoryId();
        if(Objects.nonNull(informationCategoryId)){
            //获取资讯类型的祖级
            InformationCategory informationCategory = informationCategoryService.selectInformationCategoryById(informationCategoryId);
            if(Objects.nonNull(informationCategory)){
                String ancestors = informationCategory.getAncestors();
                ancestors = ancestors + "," + informationCategoryId;
                information.setInformationCategoryAncestors(ancestors);
            }
        }
    }

    /**
     * 新增保存资讯信息
     *
     * @param information 资讯信息
     * @return 结果
     */
    @Override
    public int insertInformation(Information information) {
        setInformationAncestors(information);
        int result = informationMapper.insertInformation(information);
        return result;
    }

    @Async
    protected void sendEmailToSubscriber(Information information) {
        Long informationId = information.getInformationId();
        //判断是否推送给所有用户
        String toAllUser = information.getToAllUser();
        Long categoryId = information.getInformationCategoryId();
        if (InformationToAllUser.YES.getCode().equals(toAllUser)) {
            //推送给所有用户
            Customer queryCustomer = new Customer();
            List<Customer> customers = customerService.selectCustomerList(queryCustomer);
            if (!CollectionUtils.isEmpty(customers)) {
                for (Customer customer : customers) {
                    String email = customer.getEmail();
                    sendEmail(information, email);
                }
            }
        } else {
            //只推送给订阅用户
            InformationCategorySubscribe query = new InformationCategorySubscribe();
            query.setCategoryId(categoryId);
            List<InformationCategorySubscribe> informationCategorySubscribes = informationCategorySubscribeService.selectInformationCategorySubscribeListDistinctUserId(query);
            if (!CollectionUtils.isEmpty(informationCategorySubscribes)) {
                for (int i = 0; i < informationCategorySubscribes.size(); i++) {
                    InformationCategorySubscribe subscribe = informationCategorySubscribes.get(i);
                    Long userId = subscribe.getUserId();
                    if (Objects.nonNull(userId)) {
                        SysUser sysUser = sysUserService.selectUserById(userId);
                        if (Objects.nonNull(sysUser)) {
                            String toEmail = sysUser.getEmail();
                            //修改重复推送开关状态，判断是否重新推送，已经推送给的客户。
                            String rePublish = information.getRePublish();
                            if(InformationRePublish.NO.getCode().equals(rePublish)){
                                //推动给所有用户或者订阅用户，不校验是否已经推送过
                                InformationPushLog queryPushLog = new InformationPushLog();
                                queryPushLog.setToEmail(toEmail);
                                queryPushLog.setInformationId(informationId);
                                List<InformationPushLog> informationPushLogs = pushLogService.selectInformationPushLogList(queryPushLog);
                                if(!CollectionUtils.isEmpty(informationPushLogs)){
                                    continue;
                                }
                            }
                            if (StringUtils.isNotEmpty(toEmail)) {
                                sendEmail(information, toEmail);
                            }
                        }
                    }
                }
            }
        }
    }

    public String encodeUriComponent(String input) {
        try {
            return URLEncoder.encode(input, "UTF-8")
                    .replaceAll("\\+", "%20")
                    .replaceAll("\\%21", "!")
                    .replaceAll("\\%27", "'")
                    .replaceAll("\\%28", "(")
                    .replaceAll("\\%29", ")")
                    .replaceAll("\\%7E", "~");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public void sendEmail(Information information, String email) {
        String subject = information.getTitle();
        String content = information.getContent();
        Map<String, String> params = new HashMap<String, String>();
        Long informationId = information.getInformationId();
        String code = CryptoUtil.encrypt(informationId.toString());
        params.put("detailUrl", websiteHost + "/news-detail?code=" + encodeUriComponent(code));
        params.put("title", subject);
        try {
            content = new Markdown4jProcessor().process(content);
        } catch (IOException e) {
            e.printStackTrace();
            content = "";
        }
        params.put("content", content);
        try {
            mailService.sendMail(fromMail, email, subject, "news", params);
            log.info(" {} subscribe mail sent successfully", email);
            //记录推送日志
            InformationPushLog pushLog = new InformationPushLog();
            pushLog.setInformationId(informationId);
            pushLog.setFromEmail(fromMail);
            pushLog.setToEmail(email);
            pushLogService.insertInformationPushLog(pushLog);
        } catch (MessagingException e) {
            log.error("Error sending subscribe mail", e);
        }catch (MailException e1){
            log.error("Error sending subscribe mail", e1);
        }
    }

    /**
     * 修改保存资讯信息
     *
     * @param information 资讯信息
     * @return 结果
     */
    @Override
    public int updateInformation(Information information) {
        setInformationAncestors(information);
        int result = informationMapper.updateInformation(information);
        //判断是不是修改为发布状态
        String publishStatus = information.getPublishStatus();
        if(InformationPublishStatus.PUBLISHED.getCode().equals(publishStatus)){
            information = selectInformationById(information.getInformationId());
            sendEmailToSubscriber(information);
        }
        return result;
    }

    /**
     * 删除资讯管理信息
     *
     * @param deptId 资讯ID
     * @return 结果
     */
    @Override
    public int deleteInformationById(Long deptId) {
        return informationMapper.deleteInformationById(deptId);
    }

}
